<?php

include 'config.php';

// autoloader for the ogc classes and possibly others
function __autoload($class_name) 
{
    require_once strtolower($class_name) . '.php';
}

// LAB OGC class, SOS implementation example
class LAB_SOS extends SOS
{
    // variable to hold a database connection, mysqli or anything else  
    protected $db = NULL;

    public function __construct()
    {
        parent::__construct();

        // some LAB specific substitution parameters
        $this->parameters['soslink'] = $GLOBALS['soslink'];
        $this->parameters['deflink'] = $GLOBALS['deflink'];
        $this->parameters['featlink'] = $GLOBALS['featlink'];
        $this->parameters['maxcount'] = $GLOBALS['max_record_count'];

        // initialise templates
        $this->allowed_operations['GetCapabilities']['template'] = $GLOBALS['temp_getcapabilities'];
        $this->allowed_operations['DescribeSensor']['template']  = $GLOBALS['temp_describesensor'];
        $this->allowed_operations['GetObservation']['template']  = $GLOBALS['temp_getobservation'];

        $this->connect_db();
    }

    public function __destruct()
    {
        $this->close_db();

        parent::__destruct();
    }

    // connect, close, retrieve data from mysql
    private function connect_db()
    {
        // already opened ?
        if ( is_object($this->db) )
            return true;

        $this->db = new mysqli($GLOBALS['priv_db'], $GLOBALS['priv_dbuser'], 
            $GLOBALS['priv_dbpass'], $GLOBALS['priv_dbname']); 

        if ( mysqli_connect_errno() )
        {
            $this->exception[] = array( 'code', 'NoApplicableCode', 'message', 'Error connecting to database.' );
            $this->db = -1;
            return false;
        }

        return true;
    }

    private function close_db()
    {
        if ( !is_object($this->db) )
            return true;

        $this->db->close();
        unset($this->db);

        return true;
    }

    /**
     * Retrieves analysis data from the database, assumes sanitized variables.
     * Also assumes that at least the timestamp is included in the fields request.
     *
     * Returns an empty array on error, or the results array on success
     */
    private function retrieve_analysis( $platform, $pid, $fields, $tstart, $tend )
    {
        $res = '';

        if ( !is_object($this->db) )
            return $res;

        $platform = strtolower($platform);

        $stmt = $this->db->prepare( "SELECT $fields FROM $platform WHERE " .
            "timestamp >= ? AND timestamp <= ? LIMIT {$GLOBALS['max_record_count']}" ) or die('db query error.');

        $stmt->bind_param( 'ii', $tstart, $tend );

        if ( $stmt->execute() == FALSE )
        {
            $stmt->close();
            return $res;
        }

        $meta = $stmt->result_metadata();
        while ($field = $meta->fetch_field())
        {
            $params[] = &$row[$field->name];
        }

        call_user_func_array(array($stmt, 'bind_result'), $params);

        while ( $stmt->fetch() )
        {
            $row['timestamp'] = strftime( '%G-%m-%dT%H:%M:%S%z', $row['timestamp'] );
            $res .= implode( ',', $row ) . ',0@@';
        }

        $stmt->close();

        return $res;
    }


    public function getObservationReply() 
    {
        // platform information
        $prop = $this->operationref['params']['observedProperty']['value'];
        if ( $prop == '' )
        {
            $this->exception[] = array( 'code', 'InvalidParameterValue', 'message', "Invalid observed property $prop." );
            return false;
        }

        $items = explode( ':', $prop );

        if ( in_array( strtolower($items[3]), $GLOBALS['platforms'] ) == FALSE )
        {
            $this->exception[] = array( 'code', 'InvalidParameterValue', 'message', "Invalid observed property $prop." );
            return false;
        }
        if ( $items[4] != 1 )
        {
            $this->exception[] = array( 'code', 'InvalidParameterValue', 'message', "Invalid observed property $prop." );
            return false;
        }
        if ( strtolower($items[5]) != 'analysis' )
        {
            $this->exception[] = array( 'code', 'InvalidParameterValue', 'message', "Invalid observed property $prop." );
            return false;
        }

        $this->parameters['platform'] = $items[3];
        $this->parameters['pid']      = $items[4];

        // time information
        $tmp =  date_parse($this->operationref['params']['beginPosition']['value']);
        $tstart = gmmktime( $tmp['hour'], $tmp['minute'], $tmp['second'], $tmp['month'],
                       $tmp['day'], $tmp['year'] );

        if ( $this->operationref['params']['endPosition']['value'] == ''  )
        {
            if ( $this->operationref['params']['endIndeterminate']['value'] == 'now' )
            {
                $tend = time();
            }
            else
            {
                return 'Unsupported endPosition definitions.';
            }
            $this->operationref['params']['endPosition']['value'] = 
                strftime( '%G-%m-%dT%H:%M:%S%z', $tend );
        }
        else
        {
            $tmp =  date_parse($this->operationref['params']['endPosition']['value']);
            $tend = gmmktime( $tmp['hour'], $tmp['minute'], $tmp['second'], $tmp['month'],
                       $tmp['day'], $tmp['year'] );
        }
        
        if ( $tstart >= $tend || $tstart < $GLOBALS['date_start'] )
        {
            $this->exception[] = array( 'code', 'InvalidParameterValue', 'message', "Invalid observed date specification $tstart - $tend." );
            return false;
        }

        $this->parameters['data'] = $this->retrieve_analysis( $items[3], $items[4],
            'timestamp, dolphin, rms, sound_maximum', $tstart, $tend );
        $this->parameters['count'] = substr_count( $this->parameters['data'], '@@' );
        $this->parameters['data'] = preg_replace( '/@@$/', '', $this->parameters['data'] );

        return true;
    }

    # overload this to set the lowest allowed start time
    public function getCapabilities()
    {
        $this->parameters['beginPosition'] = 
            strftime( '%G-%m-%dT%H:%M:%S%z', $GLOBALS['date_start'] );

        return parent::getCapabilities();
    }

    # handles the local implementation of DescribeSensor (checks for valid procedure field)
    public function describeSensorReply()
    {
        $proc = $this->operationref['params']['procedure']['value'];
        if ( $proc == '' )
        {
            $this->exception[] = array( 'code' => 'InvalidParameterValue', 'message',  "Procedure field was not found - $proc" );
            return false;
        }
        $items = explode( ':', $proc );

        if ( in_array( strtolower($items[3]), $GLOBALS['platforms'] ) == FALSE )
        {
            $this->exception[] = array( 'code' => 'InvalidParameterValue', 'message' => "Illegal procedure field - $proc." );
            return false;
        }

        if ( $items[4] != 1 )
        {
            $this->exception[] = array( 'code' => 'InvalidParameterValue', 'message' => "Illegal procedure field - $proc." );
            return false;
        }
    
        $this->parameters['platform'] = strtolower($items[3]);
        $this->parameters['pid']      = $items[4];
        
        return true;    
    }

}


$ds = new LAB_SOS;

echo $ds->handleRequest();
?>
